
using System;


namespace NSQLObjects.VS2010Plugin.Syntax {
partial class Parser {
	public const int _EOF = 0;
	public const int _ident = 1;
	public const int _number = 2;
	public const int _block = 3;
	public const int _dblock = 4;
	public const int _string = 5;
	public const int _comment = 6;
	public const int _comment2 = 7;
	public const int maxT = 39;

	const bool T = true;
	const bool x = false;
	const int minErrDist = 2;
	
	public Scanner scanner;
	public Errors  errors;

	public Token t;    // last recognized token
	public Token la;   // lookahead token
	int errDist = minErrDist;



	public Parser(Scanner scanner) {
		this.scanner = scanner;
		errors = new Errors();
	}

	void SynErr (int n) {
		if (errDist >= minErrDist) errors.SynErr(la.line, la.col, n);
		errDist = 0;
	}

	public void SemErr (string msg) {
		if (errDist >= minErrDist) errors.SemErr(t.line, t.col, msg);
		errDist = 0;
	}
	
	void Get () {
		for (;;) {
			t = la;
			la = scanner.Scan();
			if (la.kind <= maxT) { ++errDist; break; }

			la = t;
		}
	}
	
	void Expect (int n) {
		if (la.kind==n) Get(); else { SynErr(n); }
	}
	
	bool StartOf (int s) {
		return set[s, la.kind];
	}
	
	void ExpectWeak (int n, int follow) {
		if (la.kind == n) Get();
		else {
			SynErr(n);
			while (!StartOf(follow)) Get();
		}
	}


	bool WeakSeparator(int n, int syFol, int repFol) {
		int kind = la.kind;
		if (kind == n) {Get(); return true;}
		else if (StartOf(repFol)) {return false;}
		else {
			SynErr(n);
			while (!(set[syFol, kind] || set[repFol, kind] || set[0, kind])) {
				Get();
				kind = la.kind;
			}
			return StartOf(syFol);
		}
	}

	
	void TableDef() {
		while (StartOf(1)) {
			while (!(StartOf(2))) {SynErr(40); Get();}
			SyntaxElement();
		}
	}

	void SyntaxElement() {
		switch (la.kind) {
		case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: {
			Resword();
			AddKeyword(t); 
			break;
		}
		case 28: case 29: case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: case 38: {
			Delim();
			break;
		}
		case 1: {
			Get();
			break;
		}
		case 27: {
			Connection();
			break;
		}
		case 2: {
			Get();
			AddNumber(t); 
			break;
		}
		case 3: {
			Get();
			AddBlock(t, false); 
			break;
		}
		case 4: {
			Get();
			AddBlock(t, true); 
			break;
		}
		case 6: {
			Get();
			AddComment(t); 
			break;
		}
		case 7: {
			Get();
			AddComment(t); 
			break;
		}
		case 5: {
			Get();
			AddString(t); 
			break;
		}
		default: SynErr(41); break;
		}
	}

	void Resword() {
		switch (la.kind) {
		case 8: {
			Get();
			break;
		}
		case 9: {
			Get();
			break;
		}
		case 10: {
			Get();
			break;
		}
		case 11: {
			Get();
			break;
		}
		case 12: {
			Get();
			break;
		}
		case 13: {
			Get();
			break;
		}
		case 14: {
			Get();
			break;
		}
		case 15: {
			Get();
			break;
		}
		case 16: {
			Get();
			break;
		}
		case 17: {
			Get();
			break;
		}
		case 18: {
			Get();
			break;
		}
		case 19: {
			Get();
			break;
		}
		case 20: {
			Get();
			break;
		}
		case 21: {
			Get();
			break;
		}
		case 22: {
			Get();
			break;
		}
		case 23: {
			Get();
			break;
		}
		case 24: {
			Get();
			break;
		}
		case 25: {
			Get();
			break;
		}
		case 26: {
			Get();
			break;
		}
		default: SynErr(42); break;
		}
	}

	void Delim() {
		switch (la.kind) {
		case 28: {
			Get();
			break;
		}
		case 29: {
			Get();
			break;
		}
		case 30: {
			Get();
			break;
		}
		case 31: {
			Get();
			break;
		}
		case 32: {
			Get();
			break;
		}
		case 33: {
			Get();
			break;
		}
		case 34: {
			Get();
			break;
		}
		case 35: {
			Get();
			break;
		}
		case 36: {
			Get();
			break;
		}
		case 37: {
			Get();
			break;
		}
		case 38: {
			Get();
			break;
		}
		default: SynErr(43); break;
		}
	}

	void Connection() {
		Expect(27);
		AddKeyword(t); 
		Expect(5);
		AddString(t); AddConnectionString(t); 
	}



	public void Parse() {
		la = new Token();
		la.val = "";		
		Get();
		TableDef();

    Expect(0);
	}
	
	static readonly bool[,] set = {
		{T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,x, x},
		{x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,x, x},
		{T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,x, x}

	};
} // end Parser


public class Errors {
	public int count = 0;                                    // number of errors detected
	public NSQLObjects.VS2010Plugin.Syntax.IReport ReportErrors { get; set; }
	public string FileName { get; set; }

	public void SynErr (int line, int col, int n) {
		string s;
		switch (n) {
			case 0: s = "EOF expected"; break;
			case 1: s = "ident expected"; break;
			case 2: s = "number expected"; break;
			case 3: s = "block expected"; break;
			case 4: s = "dblock expected"; break;
			case 5: s = "string expected"; break;
			case 6: s = "comment expected"; break;
			case 7: s = "comment2 expected"; break;
			case 8: s = "\"entity\" expected"; break;
			case 9: s = "\"inherits\" expected"; break;
			case 10: s = "\"query\" expected"; break;
			case 11: s = "\"order\" expected"; break;
			case 12: s = "\"by\" expected"; break;
			case 13: s = "\"returns\" expected"; break;
			case 14: s = "\"fetch\" expected"; break;
			case 15: s = "\"update\" expected"; break;
			case 16: s = "\"fields\" expected"; break;
			case 17: s = "\"code\" expected"; break;
			case 18: s = "\"import\" expected"; break;
			case 19: s = "\"namespace\" expected"; break;
			case 20: s = "\"readonly\" expected"; break;
			case 21: s = "\"protected\" expected"; break;
			case 22: s = "\"private\" expected"; break;
			case 23: s = "\"like\" expected"; break;
			case 24: s = "\"compute\" expected"; break;
			case 25: s = "\"default\" expected"; break;
			case 26: s = "\"type\" expected"; break;
			case 27: s = "\"connection\" expected"; break;
			case 28: s = "\".\" expected"; break;
			case 29: s = "\",\" expected"; break;
			case 30: s = "\";\" expected"; break;
			case 31: s = "\"*\" expected"; break;
			case 32: s = "\"?\" expected"; break;
			case 33: s = "\":\" expected"; break;
			case 34: s = "\"-\" expected"; break;
			case 35: s = "\"{\" expected"; break;
			case 36: s = "\"}\" expected"; break;
			case 37: s = "\"(\" expected"; break;
			case 38: s = "\")\" expected"; break;
			case 39: s = "??? expected"; break;
			case 40: s = "this symbol not expected in TableDef"; break;
			case 41: s = "invalid SyntaxElement"; break;
			case 42: s = "invalid Resword"; break;
			case 43: s = "invalid Delim"; break;

			default: s = "error " + n; break;
		}
		
		ReportErrors.Report(true, FileName, line, col, s);
		count++;
	}

	public void SemErr (int line, int col, string s) {
		ReportErrors.Report(true, FileName, line, col, s);
		count++;
	}
	
	public void SemErr (string s) {
		ReportErrors.Report(true, FileName, 0, 0, s);
		count++;
	}
	
	public void Warning (int line, int col, string s) {
		ReportErrors.Report(false, FileName, line, col, s);
	}
	
	public void Warning(string s) {
		ReportErrors.Report(false, FileName, 0, 0, s);
	}
} // Errors


public class FatalError: Exception {
	public FatalError(string m): base(m) {}
}
}
